/*
 * Basterd Game Engine
 *
 * Copyright (C) 2011 by TEJO-UFC
 *
 * 		This file is part of the "Basterd Graphics Engine"
 * 		See the copyright notice in basterd.h for conditions of distribution and use.
 *
 * NOTE: This header contains THIS.
 */

#ifndef BASTERD_ENGINE_THREAD_CLASS_H_
#define BASTERD_ENGINE_THREAD_CLASS_H_



#include "SynchronizedValue.h"


namespace basterd
{
		typedef unsigned int uint32;

		/** @brief Defines an interface to be implemented by any class whose instances are intended to be executed as a thread.
		 *
		 *  @remarks
		 *		This interface is designed to provide a common protocol for objects that wish
		 *		to execute code while they are active. Being active simply means that a thread
		 *		has been started and has not yet been stopped.
		 *  @par
		 *		In addition, Runnable provides the means for a class to be active while not
		 *		subclassing Thread. A class that implements Runnable can run without subclassing
		 *		Thread by creating a Thread instance and passing itself in as the target.
		 *
		 *  @see Thread
		 */
		class Runnable
		{
		public:

			/** Destructor, which must be overridden.
			 */
			virtual ~Runnable(void) {}

			/** When an object implementing interface Runnable is used
			 *   to create a thread, starting the thread causes the object's <em>run()</em>
			 *	method to be called in that separately executing thread. The contract of the
			 *	method <em>run</em> is that it may take any action whatsoever.
			 *
			 * @see Thread.run()
			 */
			virtual void run(void) = 0;

		};

		/** @brief This class encapsulates a thread, ie, an independent (possibily concurrent) <em>execution thread</em>
		 *
		 *  @remarks
		 *		A Thread is a thread of execution in a program. The engine allows an application to have multiple threads of
		 *		execution running concurrently. Every thread has a priority, so threads with higher priority are executed in
		 *		preference to threads with lower priority. Execution priority can be set by calling setPriority() before the
		 *		thread is started. This class is strongly inpired by Java's class.
		 *  @par
		 *		There are two ways to create a new thread of execution. The most common one is subclassing and overridding
		 *		Thread:run() method. Another way to create a thread is subclassing the Runnable class and passing an instance
		 *		of Runnable to Thread's constructor. This will cause the thread to call the runnable's run() method.
		 *		The second approach only is recomended when a class has more responsibilities than just having methods, but to
		 *		perform some active processing.
		 *	@par
		 *		Thread have the advantage of getting blocked if needed and let the application flow run as if nothing hapenned.
		 *		File loading can be done in background by threads, for example, so application loading gets much faster than if
		 *		it got blocked every time it needs to read/write from/to a file or network. On the other hand, thread concurrency
		 *		can also bring some problems to your applications, by adding read/write access complexity to variables, for example.
		 *		Other problem is that we can't have sweet, synchronized methods like we were programing Java.
		 *	@par
		 *		In addition to threading classes, there were added utility macros and classes. Although C++ does not come with
		 *		native threading support, it haves a nice scheme for doing almost enything by combining OO design and macros.
		 *		Take a look at CGE_SYNCHRONIZE macro and MutexLocker class for multi-threaded programming with less headaches.
		 *
		 *  @see Runnable, Mutex
		 */
		class Thread
		{
		public:

			/**
			 * Enumerates all valid thread states in the engine.
			 */
			enum ThreadState
			{
				/// Initial state, indicating the thread is not running anymore
				THREAD_IDLE,
				/// The thread is created in the OS and is waiting to be ran
				THREAD_READY,
				/// The thread is created in the OS and is currently running
				THREAD_RUNNING,
				/** The thread was created or running, and was asked to stop
				 *  Please observe that this state is similar to THREAD_IDLE, but less safe because
				 *  the thread was stopped forcibly.
				 */
				THREAD_STOPPED
			};

			/// Maximum priority that can be associated with a thread (100)
			static uint32 PRIORITY_MAX;
			/// Minimum priority that can be associated with a thread (0)
			static uint32 PRIORITY_MIN;
			/// Default priority assigned to threads
			static uint32 PRIORITY_NORMAL;

			/** Default constructor
			 */
			Thread(void);

			/** Runnable constructor, providing the means of a class run as thread
			*	without subclassing Thread itself.
			 */
			Thread( Runnable* runnable );

			/** Destructor
			 */
			virtual ~Thread(void);

			/** Sets the priority for this thread
			 *  @remarks Be sure you don't call this method after you call start()
			 *  @see Thread::MAX_PRIORITY, Thread::MIN_PRIORITY, Thread::NORMAL_PRIORITY
			 */
			void setPriority( uint32 priority );

			/** Gets this thread's priority
			 *  @see Thread::MAX_PRIORITY, Thread::MIN_PRIORITY, Thread::NORMAL_PRIORITY
			 */
			uint32 getPriority(void) const;

			/** Setups everything and starts this thread, calling the run method
			 *
			 *  This method starts the thread execution.
			 *  Only idle and stopped threads can be started.
			 *  Calling this method on a ready or running thread will have no effect.
			 *
			 *  @remarks If you need to set priority, be sure it is done before you call this method.
			 */
			void start(void);

			/** Forcibly stops this thread's execution.
			 *  Please observe that the actual result is hard do predict because it
			 *  depends on the user's implementation and the resources it allocates.
			 *
			 *  [use at your own risk, only you know what you are doing]
			 */
			void stop(void);

			/** Causes this thread to sleep for the given milliseconds
			 */
			static void sleep( uint32 milliseconds );

			/** Waits for this thread to stop
			 */
			void join(void);

			/** Tells the currently running thread to frees CPU time, allowing other threads
			 *  to execute. Observe that internal behavior depends on the underlying platform.
			 */
			static void yield(void);

			/** Checks whether this thread is running or not.
			 */
			bool isRunning(void) const;

			/** Gets the current state of this thread.
			 */
			Thread::ThreadState getState(void) const;

			/** @brief This method will be your thread main method.
			 *  @remarks This method must be implemented, 'cause it will be used as your thread's entry point,
			 *			 thus acting just like main() function in a C program -- without arguments.
			 */
			virtual void run(void);

		private:

			/** @brief Private copy-constructor
			 *
			 *  @remarks Threads are not here to be passed by copy as argument nor
			 *			 to be explicitly copied.
			 */
			Thread( const Thread& thread );

			/** @brief Private copy assignment operator
			 *
			 *  @remarks Threads are not here to be passed by copy as argument nor
			 *			 to be explicitly copied.
			 */
			Thread& operator = ( const Thread& thread );

			/** Thread callback used for internal implementation.
			 */
			#if 0 // (BASTERD_PLATFORM == BASTERD_PLATFORM_WIN32) || (BASTERD_PLATFORM == BASTERD_PLATFORM_WIN64)
				static UINT __stdcall _threadRunMethod(void* param);
			#else
				static void* _threadRunMethod (void* param);
			#endif

			/** Is this thread using the runnable interface to provide a run method?
			 */
			Runnable* _runnable;

			#if 0 // (BASTERD_PLATFORM == BASTERD_PLATFORM_WIN32) || (BASTERD_PLATFORM == BASTERD_PLATFORM_WIN64)
				/// Win32 thread
				HANDLE _thread;
			#else
				/// pthread rulez!!
				pthread_t _thread;
			#endif

			/** Holds this thread's priority
			 */
			uint32 _priority;

			/** Is this thread running? This means start() was called before.
			 *  When this flag is true, it is not
			 */
			::basterd::util::SynchronizedValue< Thread::ThreadState > _state;
		};
}

#endif /* BASTERD_ENGINE_THREAD_CLASS_H_ */
